package com.example.jobback.common.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.TypeReference;
import com.aliyuncs.dysmsapi.model.v20170525.SendSmsResponse;
import com.aliyuncs.exceptions.ClientException;
import com.example.jobback.common.service.CommonService;
import com.example.jobback.config.AliyunConfig;
import com.example.jobback.config.AuthConfig;
import com.example.jobback.mapper.*;
import com.example.jobback.po.*;
import com.example.jobback.req.common.page.PageReq;
import com.example.jobback.req.common.password.RecoverPasswordReq;
import com.example.jobback.resp.common.city.GetCityResp;
import com.example.jobback.resp.common.city.GetProvinceByCityResp;
import com.example.jobback.resp.common.company.GetCompanyIndustryResp;
import com.example.jobback.resp.common.position.GetPositionAllMessageResp;
import com.example.jobback.resp.common.position.category.GetPositionCategoryResp;
import com.example.jobback.resp.common.position.industry.GetPositionIndustryResp;
import com.example.jobback.resp.common.position.name.GetPositionNameByIndustryIdResp;
import com.example.jobback.resp.common.position.name.GetPositionNameResp;
import com.example.jobback.resp.common.province.GetProvinceResp;
import com.example.jobback.result.Result;
import com.example.jobback.service.common.UserCommonService;
import com.example.jobback.service.seeker.SeekerCrossService;
import com.example.jobback.util.CACHEUtil;
import com.example.jobback.util.PhoneNumberUtils;
import com.example.jobback.util.SMSUtil;
import com.example.jobback.util.SecureEncryptionUtil;
import io.swagger.v3.core.util.Json;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.Random;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

import static com.example.jobback.util.RedisConstants.*;
import static java.time.LocalDateTime.now;

/**
 * @ClassName: CommonServiceImpl
 * @Description:
 * @Author: lhb
 * @Date: 2025/5/11
 */

@Service
public class CommonServiceImpl implements CommonService {


    private final AliyunConfig aliyunConfig;

    private final ProvinceMapper provinceMapper;

    private final CityMapper cityMapper;


    private final CompanyIndustryMapper companyIndustryMapper;


    private final PositionCategoryMapper positionCategoryMapper;


    private final PositionNameMapper positionNameMapper;

    private final AuthConfig authConfig;


    private final PositionIndustryMapper positionIndustryMapper;

    private final CACHEUtil cacheUtil;

    private final PhoneNumberUtils phoneNumberUtils;

    private final UserCommonService userCommonService;

    private final Random random=new Random();

    private final SeekerCrossService seekerCrossService;

    public CommonServiceImpl(AliyunConfig aliyunConfig, CACHEUtil cacheUtil, AuthConfig authConfig, ProvinceMapper provinceMapper, CityMapper cityMapper, CompanyIndustryMapper companyIndustryMapper, PositionIndustryMapper positionIndustryMapper, PositionCategoryMapper positionCategoryMapper, PositionNameMapper positionNameMapper, PhoneNumberUtils phoneNumberUtils, UserCommonService userCommonService, SeekerCrossService seekerCrossService) {
        this.aliyunConfig = aliyunConfig;
        this.cacheUtil = cacheUtil;
        this.authConfig = authConfig;
        this.provinceMapper = provinceMapper;
        this.cityMapper = cityMapper;
        this.companyIndustryMapper = companyIndustryMapper;
        this.positionIndustryMapper = positionIndustryMapper;
        this.positionCategoryMapper = positionCategoryMapper;
        this.positionNameMapper = positionNameMapper;
        this.phoneNumberUtils = phoneNumberUtils;
        this.userCommonService = userCommonService;
        this.seekerCrossService = seekerCrossService;
    }

    /**
     * @Description: 发送验证码
     * @param phone
     * @return Result<Object>
     * @Author lhb
     * @CreateTime 2025/5/29 21:35
     */
    @Override
    public Result<Object> sendPhoneCode(String phone) throws Exception {
        String AccessKey=aliyunConfig.getAccessKeyId();
        String AccessSecret=aliyunConfig.getAccessKeySecret();
        //签名模版
        String templateCode="SMS_154950909";
        String signName="阿里云短信测试";
        String code = String.format("%04d", random.nextInt(10000));
        try {
            // 发送短信并获取响应
            SendSmsResponse response = SMSUtil.sendMessage(signName, templateCode, phone, code, AccessKey, AccessSecret);
            if ("OK".equals(response.getCode())) {
                // 存储验证码到Redis
                String phoneAes = SecureEncryptionUtil.encrypt(phone, authConfig.getPhoneSecret());
                String phoneKey = PHONE_KEY + phoneAes;
                cacheUtil.set(phoneKey,code,PHONE_TTL, TimeUnit.MINUTES);
                return Result.success("验证码已发送，请注意查收");
            } else {
                System.out.println("电话号码："+phone+":发送失败："+response.getMessage());
                return Result.error("短信发送失败：" + response.getMessage()+"-----建议使用默认验证码0000");
            }
        } catch (ClientException e) {
            e.printStackTrace();
            System.out.println("电话号码："+phone+":发送异常："+e.getErrMsg());
            return Result.error("短信发送异常：" + e.getErrMsg()+"-----建议使用默认验证码0000");
        }
    }

    @Override
    public Result<Object> decryptPhone(String phoneAes) throws Exception {
        phoneAes = phoneAes.replace(" ", "+");
        String phone = SecureEncryptionUtil.decrypt(phoneAes, authConfig.getPhoneSecret());
        return Result.success(phone);
    }

    @Override
    public Result<Object> decryptPassword(String passwordAes) {
        passwordAes = passwordAes.replace(" ", "+");
        String password = null;
        try {
            password = SecureEncryptionUtil.decrypt(passwordAes, authConfig.getPasswordSecret());
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
        return Result.success(password);
    }

    @Override
    public Result<Object> encryptPassword(String password) {
        String passwordAes=null;
        try {
            passwordAes = SecureEncryptionUtil.encrypt(password, authConfig.getPasswordSecret());
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
        return Result.success(passwordAes);
    }

    /**
     * @Description: 获取所有省份
     * @return Result<List<GetProvinceResp>>
     * @Author lhb
     * @CreateTime 2025/7/5 10:37
     */
    @Override
    public Result<List<GetProvinceResp>> getAllProvinces() {
        List<GetProvinceResp> respList=new ArrayList<>();
        String provincesJson = cacheUtil.get(PROVINCE_KEY);
        List<Province> provinces=new ArrayList<>();
        if(provincesJson!=null){
            provinces= JSON.parseObject(provincesJson, new TypeReference<>() {});
        }
        if(provinces.isEmpty()){
            provinces=provinceMapper.getAllProvinces();
            if(!provinces.isEmpty()){
                provincesJson = JSON.toJSONString(provinces);
                cacheUtil.set(PROVINCE_KEY,provincesJson,PROVINCE_TTL,TimeUnit.HOURS);
            }
        }
        if(provinces.isEmpty()) throw new NullPointerException("数据未空");
        for (Province province : provinces) {
            GetProvinceResp resp=new GetProvinceResp();
            BeanUtils.copyProperties(province,resp);
            respList.add(resp);
        }
        return Result.success(respList);
    }

    /**
     * @Description: 根据省份id返回城市列表
     * @param id
     * @return Result<Object>
     * @Author lhb
     * @CreateTime 2025/7/5 11:13
     */
    @Override
    public Result<List<GetCityResp>> getCitiesByProvinceId(Long id) {
        List<GetCityResp> respList=new ArrayList<>();
        String cityJson = cacheUtil.get(CITY_PROVINCE_ID_KEY+id.toString());
        List<City> cities=new ArrayList<>();
        if(cityJson!=null){
            cities= JSON.parseObject(cityJson, new TypeReference<>() {});
        }
        if(cities.isEmpty()){
            cities=cityMapper.getCitiesByProvinceId(id);
            if(!cities.isEmpty()){
                cityJson = JSON.toJSONString(cities);
                cacheUtil.set(CITY_PROVINCE_ID_KEY+ id,cityJson,
                        CITY_PROVINCE_ID_TTL,TimeUnit.HOURS);
            }
        }
        if(cities.isEmpty()) throw new NullPointerException("数据未空");
        for (City city : cities) {
            GetCityResp resp=new GetCityResp();
            BeanUtils.copyProperties(city,resp);
            respList.add(resp);
        }
        return Result.success(respList);
    }

    /**
     * @Description: 获取公司行业列表
     * @return Result<List<GetCompndustryResp>>
     * @Author lhb
     * @CreateTime 2025/7/5 16:53
     */
    @Override
    public Result<List<GetCompanyIndustryResp>> getAllCompanyIndustries() {
        List<GetCompanyIndustryResp> respList=new ArrayList<>();
        String companyIndustriesJson = cacheUtil.get(COMPANY_INDUSTRY_KEY);
        List<CompanyIndustry> companyIndustries=new ArrayList<>();
        if(companyIndustriesJson!=null){
            companyIndustries= JSON.parseObject(companyIndustriesJson, new TypeReference<>() {});
        }
        if(companyIndustries.isEmpty()){
            companyIndustries=companyIndustryMapper.getAllCompanyIndustries();
            if(!companyIndustries.isEmpty()){
                companyIndustriesJson = JSON.toJSONString(companyIndustries);
                cacheUtil.set(COMPANY_INDUSTRY_KEY,companyIndustriesJson,COMPANY_INDUSTRY_TTL,TimeUnit.HOURS);
            }
        }
        if(companyIndustries.isEmpty()) throw new NullPointerException("数据未空");
        for (CompanyIndustry companyIndustry : companyIndustries) {
            GetCompanyIndustryResp resp=new GetCompanyIndustryResp();
            BeanUtils.copyProperties(companyIndustry,resp);
            respList.add(resp);
        }
        return Result.success(respList);
    }

    /**
     * @Description: 获取职位行业列表
     * @return Result<List<GetPositindustryResp>>
     * @Author lhb
     * @CreateTime 2025/7/6 13:50
     */
    @Override
    public Result<List<GetPositionIndustryResp>> getAllPositionIndustries() {
        List<GetPositionIndustryResp> respList=new ArrayList<>();
        String positionIndustriesJson = cacheUtil.get(POSITION_INDUSTRY_KEY);
        List<PositionIndustry> positionIndustries=new ArrayList<>();
        if(positionIndustriesJson!=null){
            positionIndustries= JSON.parseObject(positionIndustriesJson, new TypeReference<>() {});
        }
        if(positionIndustries.isEmpty()){
            positionIndustries=positionIndustryMapper.getAllPositionIndustries();
            if(!positionIndustries.isEmpty()){
                positionIndustriesJson = JSON.toJSONString(positionIndustries);
                cacheUtil.set(POSITION_INDUSTRY_KEY,positionIndustriesJson,POSITION_INDUSTRY_TTL,TimeUnit.HOURS);
            }
        }
        if(positionIndustries.isEmpty()) throw new NullPointerException("数据未空");
        for (PositionIndustry positionIndustry : positionIndustries) {
            GetPositionIndustryResp resp=new GetPositionIndustryResp();
            BeanUtils.copyProperties(positionIndustry,resp);
            respList.add(resp);
        }
        return Result.success(respList);
    }

    /**
     * @Description: 根据职位行业id返回职位类别列表
     * @param id
     * @return Result<List<GetPositiategoryResp>>
     * @Author lhb
     * @CreateTime 2025/7/6 14:05
     */
    @Override
    public Result<List<GetPositionCategoryResp>> getPositionCategoriesByIndustryId(Long id) {
        List<GetPositionCategoryResp> respList = commonGetPositionCategoriesByIndustryId(id);
        if(respList.isEmpty()) throw new NullPointerException("数据未空");
        return Result.success(respList);
    }

    /**
     * @Description: 通用方法，根据职位行业id返回职位类别列表
     * @param id
     * @return List<GetPositiategoryResp>
     * @Author lhb
     * @CreateTime 2025/7/6 14:33
     */
    private List<GetPositionCategoryResp> commonGetPositionCategoriesByIndustryId(Long id) {
        List<GetPositionCategoryResp> respList=new ArrayList<>();
        String positionCategoryJson = cacheUtil.get(POSITION_CATEGORY_INDUSTRY_ID_KEY+id.toString());
        List<PositionCategory> positionCategories=new ArrayList<>();
        if(positionCategoryJson!=null){
            positionCategories= JSON.parseObject(positionCategoryJson, new TypeReference<>() {});
        }
        if(positionCategories.isEmpty()){
            positionCategories=positionCategoryMapper.getPositionCategoriesByIndustryId(id);
            if(!positionCategories.isEmpty()){
                positionCategoryJson = JSON.toJSONString(positionCategories);
                cacheUtil.set(POSITION_CATEGORY_INDUSTRY_ID_KEY+id,positionCategoryJson,
                        POSITION_CATEGORY_INDUSTRY_ID_TTL,TimeUnit.HOURS);
            }
        }
        if(positionCategories.isEmpty()) throw new NullPointerException("数据未空");
        for (PositionCategory positionCategory : positionCategories) {
            GetPositionCategoryResp resp=new GetPositionCategoryResp();
            BeanUtils.copyProperties(positionCategory,resp);
            respList.add(resp);
        }
        return respList;
    }

    /**
     * @Description: 根据职位类别id返回职位名称列表
     * @param id
     * @return Result<List<GetPositiameResp>>
     * @Author lhb
     * @CreateTime 2025/7/6 14:17
     */
    @Override
    public Result<List<GetPositionNameResp>> getPositionNamesByCategoryId(Long id) {
        List<GetPositionNameResp> respList = commonGetPositionNamesByCategoryId(id);
        if(respList.isEmpty()) throw new NullPointerException("数据为空");
        return Result.success(respList);
    }

    /**
     * @Description: 通用方法，根据职位类别id返回职位名称列表
     * @param id
     * @return List<GetPositiameResp>
     * @Author lhb
     * @CreateTime 2025/7/6 14:38
     */
    private List<GetPositionNameResp> commonGetPositionNamesByCategoryId(Long id) {
        List<GetPositionNameResp> respList=new ArrayList<>();
        String positionNameJson = cacheUtil.get(POSITION_NAME_CATEGORY_ID_KEY+id.toString());
        List<PositionName> positionNames=new ArrayList<>();
        if(positionNameJson!=null){
            positionNames= JSON.parseObject(positionNameJson, new TypeReference<>() {});
        }
        if(positionNames.isEmpty()){
            positionNames=positionNameMapper.getPositionNamesByCategoryId(id);
            if(!positionNames.isEmpty()){
                positionNameJson = JSON.toJSONString(positionNames);
                cacheUtil.set(POSITION_NAME_CATEGORY_ID_KEY+id,positionNameJson,
                        POSITION_NAME_CATEGORY_ID_TTL,TimeUnit.HOURS);
            }
        }
        if(positionNames.isEmpty()) throw new NullPointerException("数据未空");
        for (PositionName positionName : positionNames) {
            GetPositionNameResp resp=new GetPositionNameResp();
            BeanUtils.copyProperties(positionName,resp);
            respList.add(resp);
        }
        return respList;
    }

    /**
     * @Description: 根据职位行业id返回职位名称列表
     * @param id
     * @return Result<List<GetPositiameByIndustryIdResp>>
     * @Author lhb
     * @CreateTime 2025/7/6 14:25
     */
    @Override
    public Result<List<GetPositionNameByIndustryIdResp>> getPositionNamesByIndustryId(Long id) {
        List<GetPositionNameByIndustryIdResp> respList=new ArrayList<>();
        List<GetPositionCategoryResp> categoryRespList = commonGetPositionCategoriesByIndustryId(id);
        if(categoryRespList.isEmpty()) throw new NullPointerException("数据为空");
        for (GetPositionCategoryResp getPositionCategoryResp : categoryRespList) {
            GetPositionNameByIndustryIdResp resp=new GetPositionNameByIndustryIdResp();
            resp.setGetPositionCategoryResp(getPositionCategoryResp);
            List<GetPositionNameResp> nameRespList =
                    commonGetPositionNamesByCategoryId(getPositionCategoryResp.getId());
            resp.setGetPositionNameRespList(nameRespList);
            respList.add(resp);
        }
        return Result.success(respList);
    }

    /**
     * @Description: 根据城市名称返回省份id和城市id
     * @param cityName 
     * @return Result<GetProvinceByCityResp>
     * @Author lhb
     * @CreateTime 2025/7/21 10:10
     */
    @Override
    public Result<GetProvinceByCityResp> getProvinceByCity(String cityName) {
        if(StringUtils.isBlank(cityName)) {
            throw new IllegalArgumentException("VALIDATION_ERROR：名称为空");
        }
        City city = cityMapper.getCityByCityName(cityName);
        if(Objects.isNull(city)) {
            throw new NullPointerException("无此记录");
        }
        GetProvinceByCityResp resp = new GetProvinceByCityResp();
        resp.setProvinceId(city.getProvinceId());
        resp.setCityId(city.getId());
        return Result.success(resp);
    }

    /**
     * @Description: 根据职位行业名称，职位名称返回行业，类别，名称
     * @param industryName
     * @param detailName
     * @return Result<GetPositionAllMessageResp>
     * @Author lhb
     * @CreateTime 2025/7/21 10:44
     */
    @Override
    public Result<GetPositionAllMessageResp> getPositionAllMessageByIndustryAndName(String industryName, String detailName) {
        PositionIndustry positionIndustry = positionIndustryMapper.getIndustryByName(industryName);
        if(Objects.isNull(positionIndustry)) {
            throw new NullPointerException("行业信息不存在");
        }
        List<GetPositionCategoryResp> getPositionCategoryResps = commonGetPositionCategoriesByIndustryId(positionIndustry.getId());
        if(getPositionCategoryResps.isEmpty()) {
            throw new NullPointerException("类别列表信息不存在");
        }
        List<Long> categoryIds = getPositionCategoryResps.stream()
                .map(GetPositionCategoryResp::getId)
                .filter(Objects::nonNull)
                .toList();
        List<PositionName> positionNameList = positionNameMapper.getPositionNamesByCategoryIds(categoryIds);
        for (PositionName positionName : positionNameList) {
            if(positionName.getDetailName().equals(detailName)) {
                GetPositionAllMessageResp resp = new GetPositionAllMessageResp();
                resp.setIndustryId(positionIndustry.getId());
                resp.setCategoryId(positionName.getCategoryId());
                resp.setDetailId(positionName.getId());
                return Result.success(resp);
            }
        }
        throw new NullPointerException("职位信息不存在");
    }

    /**
     * @Description: 找回密码
     * @param recoverPasswordReq
     * @return Result<Object>
     * @Author lhb
     * @CreateTime 2025/7/25 16:20
     */
    @Override
    public Result<Object> recoverPassword(RecoverPasswordReq recoverPasswordReq) {
        String name = recoverPasswordReq.getName();
        String phone = recoverPasswordReq.getPhone();
        String password = recoverPasswordReq.getNewPassword();
        String phoneAes = "";
        try {
            phoneAes = phoneNumberUtils.encryptPhone(phone);
        } catch (Exception e) {
            throw new RuntimeException("手机号格式错误");
        }
        User user = userCommonService.getUserByPhoneAes(phoneAes);
        if(Objects.isNull(user) || !Objects.equals(name, user.getName())) {
            throw new IllegalArgumentException("VALIDATION_ERROR：用户名或者手机号错误");
        }
        Long userId = user.getUserId();
        String passwordAes = "";
        try {
            passwordAes = SecureEncryptionUtil.encrypt(password,authConfig.getPasswordSecret());
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
        if(userCommonService.updateUserAuth(userId, passwordAes) == 0) {
            throw new RuntimeException("重设密码异常");
        }
        return Result.success();
    }

    /**
     * @Description: 测试使用
     * @param phoneList
     * @return Result<Object>
     * @Author lhb
     * @CreateTime 2025/7/30 9:43
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Result<Object> insertSeeker(List<String> phoneList) {
        String passwordAes=null;
        try {
            passwordAes = SecureEncryptionUtil.encrypt("1234",authConfig.getPasswordSecret());
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
        for (String phone : phoneList) {
            if (phone == null || phone.trim().isEmpty() || !phone.matches("^\\d{11}$")) {
               continue;
            }
            String phoneAes= null;
            try {
                phoneAes = SecureEncryptionUtil.encrypt(phone,authConfig.getPhoneSecret());
            } catch (Exception e) {
                throw new RuntimeException(e);
            }
            if(userCommonService.getUserByPhoneAes(phoneAes)!=null) {
                continue;
            }
            User user= userCommonService.registerUser(phoneAes);
            Long userId=user.getUserId();
            if(userCommonService.registerUserAuth(userId,passwordAes)==0) {
                throw new RuntimeException("注册失败");
            }
            //注册求职端
            // 使用BeanUtils.copyProperties将User的字段复制到Seeker
            Seeker seeker=new Seeker();
            BeanUtils.copyProperties(user, seeker);
            seeker.setCreatedAt(now());
            seeker.setUpdatedAt(now());
            if(seekerCrossService.registerSeekerTest(seeker) == 0){
                throw new RuntimeException("注册失败");
            }
        }
        return Result.success("注册成功");
    }
}
